
#include "LecteurPhraseSimple.h"
#include <stdlib.h>
#include <iostream>

using namespace std;

// TODO : Question 9 ; Introduisez dans votre grammaire une instruction "pour"
// avec une syntaxe inspirée de celle du langage C, par exemple.
////////////////////////////////////////////////////////////////////////////////
LecteurPhraseSimple::LecteurPhraseSimple(string nomFich):
    ls(nomFich)
{
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::analyse()
{
    programme();

    cout << "Syntaxe correcte." << endl;
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::programme()
{
    // <programme> ::= debut <seqInst> fin FIN_FICHIER
    sauterSymCour("debut");
    seqInst();
    sauterSymCour("fin");
    testerSymCour("<FINDEFICHIER>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::seqInst()
{
    // <seqInst> ::= <inst> ; { <inst> ; }
    do
    {
        inst();
        sauterSymCour(";");
    }
    while ((ls.getSymCour() == "<VARIABLE>") || (ls.getSymCour() == "si") || (ls.getSymCour() == "tantque")
           || (ls.getSymCour() == "repeter") || (ls.getSymCour() == "lire") || (ls.getSymCour() == "ecrire") || (ls.getSymCour()=="pour"));

    // tant que le symbole courant est un debut possible d'instruction...
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::inst()
{
    // <inst> ::= <affectation> | <instSi> | <instTq> | <instRepeter> |<instPour>
    if (ls.getSymCour() == "tantque")
    {
        instTq();
    }
    else if (ls.getSymCour() == "si")
    {
        instSi();
    }
    else if (ls.getSymCour() == "repeter")
    {
        instRepeter();
    }
    else if (ls.getSymCour() == "lire")
    {
        instLire();
    }
    else if (ls.getSymCour() == "ecrire")
    {
        instEcrire();
    }
    else if (ls.getSymCour() == "pour")
    {
        instPour();
    }
    else if (ls.getSymCour() == "<VARIABLE>")
    {
        affectation();
    }
    else
    {
        erreur("<inst>");
    }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::affectation()
{
    // <affectation> ::= <variable> = <expression>
    sauterSymCour("<VARIABLE>");
    sauterSymCour("=");
    expression();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::expression()
{
    // <expression> ::= <terme> { <opAdd> <terme> }
    terme();

    while ((ls.getSymCour() == "+") || (ls.getSymCour() == "-"))
    {
        opAdd();
        terme();
    }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::terme()
{
    // <terme> ::= <facteur> {<opMult> <facteur>}
    facteur();

    while ((ls.getSymCour() == "*") || (ls.getSymCour() == "/"))
    {
        opMult();
        facteur();
    }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opAdd()
{
    // <opAdd>  ::= + | -
    if ((ls.getSymCour() == "+") || (ls.getSymCour() == "-"))
    {
        ls.suivant();
    }
    else
    {
        erreur("<opAdd>");
    }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opMult()
{
    // <opMult>  ::= * | /
    if ((ls.getSymCour() == "*") || (ls.getSymCour() == "/"))
    {
        ls.suivant();
    }
    else
    {
        erreur("<opMult>");
    }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::facteur()
{
    // <facteur> ::= <entier>  |  <variable>  |  - <facteur>  |  <opUnaire> <expBool> | (<expBool>)
    if ((ls.getSymCour() == "<VARIABLE>") || (ls.getSymCour() == "<ENTIER>") || (ls.getSymCour() == "<CHAINE>"))
    {
        ls.suivant();
    }
    else if ((ls.getSymCour() == "-") || (ls.getSymCour() == "non"))
    {
        opUnaire();
        facteur();
    }
    else if (ls.getSymCour() == "(")
    {
        ls.suivant();
        expression();
        sauterSymCour(")");
    }
    else
    {
        erreur("<facteur>");
    }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::testerSymCour(string ch)
{
    if (ls.getSymCour() != ch)
    {
        cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne " << ls.getColonne() << endl
             << "   Attendu : " << ch << endl << "   Trouve  : " << ls.getSymCour() << endl << endl;

        exit(0);    // plus tard, on levera une exception
    }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::sauterSymCour(string ch)
{
    testerSymCour(ch);
    ls.suivant();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::erreur(string mess)
{
    cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne " << ls.getColonne() << endl
         << "   Attendu : " << mess << endl << "   Trouve  : " << ls.getSymCour() << endl << endl;

    exit(0);    // plus tard, on levera une exception
}

////////////////////////////////////////////////////////////////////////////////
// Debut 2.2
void LecteurPhraseSimple::expBool()
{
    // <expBool> ::= <termeBool> { <opOu> <termeBool> }
    termeBool();

    while ((ls.getSymCour() == "et") || (ls.getSymCour() == "ou"))
    {
        opOu();
        termeBool();
    }
}

void LecteurPhraseSimple::termeBool()
{
    // <termeBool> ::= <relation> { <opBoolEt> <relation> }
    relation();

    while ((ls.getSymCour() == "et") || (ls.getSymCour() == "ou"))
    {
        opEt();
        relation();
    }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opBool()
{
    // <opBool> ::= et | ou
    if ((ls.getSymCour() == "et") || (ls.getSymCour() == "ou"))
    {
        ls.suivant();
    }
    else
    {
        erreur("<opBool>");
    }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::relation()
{
    // <relation> ::= <expression> {<opRel> <expression>}
    expression();

    while ((ls.getSymCour() == "==") || (ls.getSymCour() == "!=") || (ls.getSymCour() == "<")
            || (ls.getSymCour() == "<=") || (ls.getSymCour() == ">") || (ls.getSymCour() == ">="))
    {
        opRel();
        expression();
    }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opRel()
{
    // <opRel> ::=  == | != | < | <= | > | >=
    if ((ls.getSymCour() == "==") || (ls.getSymCour() == "!=") || (ls.getSymCour() == "<") || (ls.getSymCour() == "<=")
            || (ls.getSymCour() == ">") || (ls.getSymCour() == ">="))
    {
        ls.suivant();
    }
    else
    {
        erreur("<opRel>");
    }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opUnaire()
{
    // <opUnaire> ::= - | non
    if ((ls.getSymCour() == "-") || (ls.getSymCour() == "non"))
    {
        ls.suivant();
    }
    else
    {
        erreur("<opBool>");
    }
}

void LecteurPhraseSimple::opEt()
{
    // <opEt>  ::= et
    if (ls.getSymCour() == "et")
    {
        ls.suivant();
    }
    else
    {
        erreur("<opEt>");
    }
}

void LecteurPhraseSimple::opOu()
{
    // <opOu>  ::= ou
    if (ls.getSymCour() == "ou")
    {
        ls.suivant();
    }
    else
    {
        erreur("<opOu>");
    }
}

// Fin 2.2
////////////////////////////////////////////////////////////////////////////////
// Debut 2.3
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instSi()
{
    // <instSi> ::= si (<expBool>) <seqInst> { sinon (<expBool>) <seqInst> }
    sauterSymCour("si");

    if (ls.getSymCour() == "(")
    {
        ls.suivant();
        expBool();
        sauterSymCour(")");
    }

    seqInst();

    while (ls.getSymCour() == "sinonsi")
    {
        ls.suivant();

        if (ls.getSymCour() == "(")
        {
            ls.suivant();
            expBool();
            sauterSymCour(")");
        }

        seqInst();
    }

    if (ls.getSymCour() == "sinon")
    {
        ls.suivant();
        seqInst();
    }

    sauterSymCour("finsi");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instTq()
{
    // <instTq> ::= tantque (<expBool>) <seqInst> fintantque
    sauterSymCour("tantque");
    sauterSymCour("(");
    expBool();
    sauterSymCour(")");
    seqInst();
    sauterSymCour("fintantque");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instRepeter()
{
    // <instRepeter> ::= repeter <seqInst> jusqua (<expBool>)
    sauterSymCour("repeter");
    seqInst();
    sauterSymCour("jusqua");
    sauterSymCour("(");
    expBool();
    sauterSymCour(")");
}

// Fin 2.3
// Debut 2.4
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instLire()
{
    // <instLire> ::= lire(<variable>)
    sauterSymCour("lire");
    sauterSymCour("(");
    sauterSymCour("<VARIABLE>");
    sauterSymCour(")");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::instEcrire()
{
    // <instEcrire> ::= ecrire (<expression> | <chaine>)
    sauterSymCour("ecrire");
    sauterSymCour("(");

    if ((ls.getSymCour() == "<VARIABLE>") || (ls.getSymCour() == "<ENTIER>") || (ls.getSymCour() == "-")
            || (ls.getSymCour() == "non") || (ls.getSymCour() == "("))
    {
        expression();
    }
    else if (ls.getSymCour() == "CHAINE")
    {
        ls.suivant();
    }

    sauterSymCour(")");
}

// Fin 2.4
////////////////////////////////////////////////////////////////////////////////
// Début 2.5
// for (i=1; i<6; i++) {
// printf("%d", i);}
// <instPour> ::= pour (<affectation> <expBool> <expression>) <seqInst> finpour
void LecteurPhraseSimple::instPour()
{
    
    
  

    sauterSymCour("pour");
    sauterSymCour("(");
    affectation();
    sauterSymCour(";");
    expBool();
    sauterSymCour(";");
    affectation();
    sauterSymCour(";");
    sauterSymCour(")");
    seqInst();
    sauterSymCour("finpour");
}


//~ Formatted by Jindent --- http://www.jindent.com
